package com.ruoyi.common.utils.bean;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.CaseFormat;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.sign.Md5Utils;
import com.ruoyi.common.utils.spring.SpringUtils;

/**
 * Bean 工具类
 * 
 * @author ruoyi
 */
public class BeanUtils extends org.springframework.beans.BeanUtils
{
    /** Bean方法名中属性名开始的下标 */
    private static final int BEAN_METHOD_PROP_INDEX = 3;

    /** * 匹配getter方法的正则表达式 */
    private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");

    /** * 匹配setter方法的正则表达式 */
    private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");

    /**
     * Bean属性复制工具方法。
     * 
     * @param dest 目标对象
     * @param src 源对象
     */
    public static void copyBeanProp(Object dest, Object src)
    {
        try
        {
            copyProperties(src, dest);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 获取对象的setter方法。
     * 
     * @param obj 对象
     * @return 对象的setter方法列表
     */
    public static List<Method> getSetterMethods(Object obj)
    {
        // setter方法列表
        List<Method> setterMethods = new ArrayList<Method>();

        // 获取所有方法
        Method[] methods = obj.getClass().getMethods();

        // 查找setter方法

        for (Method method : methods)
        {
            Matcher m = SET_PATTERN.matcher(method.getName());
            if (m.matches() && (method.getParameterTypes().length == 1))
            {
                setterMethods.add(method);
            }
        }
        // 返回setter方法列表
        return setterMethods;
    }

    /**
     * 获取对象的getter方法。
     * 
     * @param obj 对象
     * @return 对象的getter方法列表
     */

    public static List<Method> getGetterMethods(Object obj)
    {
        // getter方法列表
        List<Method> getterMethods = new ArrayList<Method>();
        // 获取所有方法
        Method[] methods = obj.getClass().getMethods();
        // 查找getter方法
        for (Method method : methods)
        {
            Matcher m = GET_PATTERN.matcher(method.getName());
            if (m.matches() && (method.getParameterTypes().length == 0))
            {
                getterMethods.add(method);
            }
        }
        // 返回getter方法列表
        return getterMethods;
    }

    /**
     * 检查Bean方法名中的属性名是否相等。<br>
     * 如getName()和setName()属性名一样，getName()和setAge()属性名不一样。
     * 
     * @param m1 方法名1
     * @param m2 方法名2
     * @return 属性名一样返回true，否则返回false
     */

    public static boolean isMethodPropEquals(String m1, String m2)
    {
        return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
    }
    public static List<Map<String, Object>> caseFormat(List<Map<String, Object>> list) throws Exception {
    	List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(list.size());
		for (int i = 0; i < list.size(); i++) {
			Map<String, Object> tmp = caseFormat(list, i);
			result.add(tmp);
		}
		list.clear();
		list.addAll(result);
		return list;
	}

	private static Map<String, Object> caseFormat(List<Map<String, Object>> list, int i) {
		Map<String, Object> data = list.get(i);
		return caseFormat(data);
	}

	public static Map<String, Object> caseFormat(Map<String, Object> data) {
		Map<String, Object> tmp = new HashMap<String, Object>();
		Iterator<String> it = data.keySet().iterator();
		while (it.hasNext()) {
			String k = it.next();
			Object obj = data.get(k);
			String key = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, k);
			tmp.put(key, obj);
		}
		return tmp;
	}
    /**
	 *     根据params及Class解析参数至实体中
	 * @param params 前端传进的参数
	 * @param c 实体的类型
	 */
	public static <T> T convert(Map<String, Object> params, Class<T> c) throws Exception {
		//JSON.toJavaObject(json, c);
		T o = c.newInstance();
		exchangeData(params, c, o);
		return o;
	}
	
	/**
	 * 根据params及Class解析参数至实体中
	 * @param params
	 * @param c
	 * @param o
	 */
	public static <T> T convert(Map<String, Object> params, Class<T> c,
			T o) throws Exception {
		exchangeData(params, c, o);
		return o;
	}
	/**
	 * 从get请求中抽取参数放进param
	 * @param param
	 */
	public static void putRequestParam(Map<String, Object> param) {
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
		Map<String, String[]> parameterMap = request.getParameterMap();
		Iterator<String> it = parameterMap.keySet().iterator();
		while(it.hasNext()) {
			String k = it.next();
			String[] v = parameterMap.get(k);
			if(v != null && v.length > 0) {
				param.put(k, v[0]);
			}
		}
	}
//	public static String getCacheKey(Map<String, Object> param,String prefix,String...keys) {
//		StringBuilder sb = new StringBuilder();
//		sb.append(prefix);
//		for (String key : keys) {
//			Object v = param.get(key);
//	    	if(v != null) {
//	    		sb.append("::");
//	    		sb.append(v.toString());
//	    	}
//		}
//		return sb.toString();
//		
//	}
	/**
	 * @param param
	 * @param prefix
	 * @return
	 * @throws JsonProcessingException
	 */
	public static String getCacheKey(Object param, String prefix) throws JsonProcessingException {
		String pageNum = ServletUtils.getParameter("pageNum");
		String pageSize = ServletUtils.getParameter("pageSize");
		//首页默认查询
		ObjectMapper mapper = new ObjectMapper();
		String str = mapper.writeValueAsString(param);
		String paramsHashKey = Md5Utils.hash(str);
		String cacheKey = prefix + "::" + pageNum + "::" + pageSize + "::" + paramsHashKey;
		return cacheKey;
	}
	/**
	 * 交换数据，将params的数据传入o
	 * @param params
	 * @param c
	 * @param o
	 * @throws NoSuchMethodException
	 * @throws ParseException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	private static <T> void exchangeData(Map<String, Object> params, Class<T> c, T o)
			throws Exception {
		List<Field> allFields = new LinkedList<Field>();
		Class<? extends Object> tmp = o.getClass();
		while(tmp != Object.class) {
			Field[] fields = tmp.getDeclaredFields();
			for (Field field : fields) {
				allFields.add(field);
			}
			tmp = tmp.getSuperclass();
		}
		for (Field field : allFields) {
			field.setAccessible(true);
			String key = field.getName();
			Object v = params.get(key);
			String value = v == null ? null : v.toString();
			if(/*StringUtils.isNotBlank(value)*/ value != null) {
				String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
				Method method = c.getMethod(methodName, field.getType());
				method.setAccessible(true);
				Object _value = null;
				if (StringUtils.isNotBlank(value) && field.getType() == Integer.class) {
					_value = Integer.parseInt(value);
				} else if (StringUtils.isNotBlank(value) && field.getType() == Date.class) {
					if(value.contains("T")) {
						_value = DateUtils.parseDate(value, "yyyy-MM-dd'T'HH:mm:ss.SSS'+08:00'");
					}else if(value.contains(".")){
						_value = DateUtils.parseDate(value, "yyyy-MM-dd HH:mm:ss.SSS");
					}else {
						_value = DateUtils.parseDate(value, "yyyy-MM-dd HH:mm:ss");
					}
				} else if (field.getType() == String.class) {//支持传入空字符串
					_value = value;
				}
				method.invoke(o, _value);
			}
		}
	}
	public static String toJSONString(Object o) throws JsonProcessingException {
		ObjectMapper mapper = new ObjectMapper();
		String str = mapper.writeValueAsString(o);
		return str;
	}
	public static <T> T toJavaBean(Class<T> c,String jsonStr) throws Exception{
		ObjectMapper mapper = new ObjectMapper();	
		T t = c.newInstance();
		t = mapper.readValue(jsonStr, c);
	    return t;
	}
	public static String getSeqId(String id,String table) {
		JdbcTemplate jdbcTemplate = SpringUtils.getBean(JdbcTemplate.class);
		String sql = "select id from " + table + " where id like ? order by id desc limit 1";
		String max = null;
		try {
			max = jdbcTemplate.queryForObject(sql, String.class,new Object[] {id + "%"});
		} catch (Exception e) {
			//e.printStackTrace();
		}
		String suffix = "000000";
		if(max == null) {
			id += suffix;
		}else {
			//String s = max.toString().split(id)[1];//前缀与后缀相同时有问题
			String s = max.toString().substring(id.length());
			long m = Long.parseLong(s);
			String incre = (m + 1) + "";
			String append = "";
			for(int i = incre.length();i < suffix.length() ;i++) {
				append += "0";
			}
			append += incre;
			id = id + append;
		}
		return id;
	}
}
